home *** CD-ROM | disk | FTP | other *** search
/ Resource for Source: C/C++ / Resource for Source - C-C++.iso / misc_src / knowhow4 / pcx.cpp < prev    next >
C/C++ Source or Header  |  1995-11-01  |  6KB  |  237 lines

  1. #include "pcx.h"
  2. #include "output.h"
  3.  
  4. void put_pcx_header(FILE* f, pcxheader* p, loc sz, int pal, int planes)
  5.     {
  6.     if(pal)
  7.     get_pcx_header("color.sys", p);
  8.  
  9.     p->bitpx = 1;
  10.     p->nplanes = planes;
  11.  
  12.     p->x1 = 0;     p->y1 = 0;    p->x2 = sz.X - 1;     p->y2 = sz.Y - 1;
  13.  
  14.     p->hres = getmaxx() + 1;        /* horiz. resolution of display   */
  15.     p->vres = getmaxy() + 1;        /* vert. resolution of display    */
  16.     p->bplin = (sz.X + 7) >> 3;     /* Bytes per line             */
  17.  
  18.     p->palinfo = 1;                    /* Palette info (1=col.,2 = grey) */
  19.  
  20.     if(f != NULL)
  21.     fwrite(p, 128, 1, f);
  22.     }
  23. /////////////////////////
  24. int get_pcx_header(pcxstream* s, pcxheader* p_h)
  25.     {
  26.     s->read((uchar*)p_h, sizeof(pcxheader));
  27.     return 1;
  28.     }
  29. ////////////////////////
  30. int get_pcx_header(FILE* file, pcxheader* p_h)
  31.     {
  32.     return fread(p_h, sizeof(pcxheader), 1, file);
  33.     }
  34. ////////////////////////
  35. int get_pcx_header(char* fname, pcxheader* p_h)
  36.     {
  37.     FILE* f;
  38.     if((f = fopen(fname, "rb")) == NULL)
  39.     return 0;
  40.     pcxheader p;
  41.     get_pcx_header(f, p_h);
  42.     fclose(f);
  43.     return 1;
  44.     }
  45. ///////////////////////////
  46. inline void pcx_put_char(uchar count, uchar ch, FILE* f)
  47.     {
  48.     if(count > 1 || (0xC0 == (0xC0 & ch)))
  49.     fputc(count | 128 | 64, f);   // Write counter
  50.     fputc(ch, f);                     // Write pattern
  51.     }
  52. //////////////////////////
  53. void pcx_scr_file(rect coord, char* name, int pal)
  54.     {
  55.     pal = 1;
  56.     FILE* f = fopen(name, "wb");
  57.  
  58.     if(coord.corner.X > getmaxx())
  59.     coord.corner.X = getmaxx();
  60.  
  61.     pcxheader p;
  62.     put_pcx_header(f, &p, loc(coord.width(), coord.height()), pal);
  63.  
  64.     imageP image = (imageP)malloc(imagesize(0, 0, coord.width(), 0));
  65.  
  66.     int x;  int y = 0;  int count = 1;
  67.     int plane;
  68.     plane = x = (N_PLANES - 1) * p.bplin;  // start of last plane
  69.     int shift = 2 * p.bplin;
  70.     int height = p.y2 - p.y1 + 1;
  71.  
  72.     getimage(coord.origin.X, coord.origin.Y,
  73.          coord.corner.X, coord.origin.Y, image);
  74.  
  75.     unsigned char ch = image->data[x];
  76.  
  77.     while(1)
  78.     {
  79.     x++;
  80.     if(!(x % p.bplin))     // end of scan line or end of plane
  81.         {
  82.         if(x != p.bplin)  // not the end of scan line
  83.         x -= shift;
  84.         else           // end of scan line
  85.         {
  86.         if(y < height)   // not last scan line
  87.             {
  88.             x = plane;
  89.             y++;
  90.             getimage(coord.origin.X, coord.origin.Y + y,
  91.             coord.corner.X, coord.origin.Y + y, image);
  92. /*  The following code, marked !! is absolutely unnecessary and ineffective.
  93.     But Painbrush use stop-on-the-scan-line technology. I don't know why.
  94.     This code is compatible with Paintbrush.
  95. */
  96.             pcx_put_char(count, ch, f);  // !!
  97.             count = 0;                   // !!
  98.             ch = image->data[x];         // !!
  99.  
  100.             }
  101.         else    // last scan line
  102.             {
  103.             pcx_put_char(count, ch, f);
  104.             break;
  105.             }
  106.         }
  107.         }
  108.  
  109.     if(ch == image->data[x])
  110.         {
  111.         if(count == 63)
  112.         {
  113.         pcx_put_char(count, ch, f);
  114.         count = 1;
  115.         }
  116.         else
  117.         count++;
  118.         }
  119.     else
  120.         {
  121.         pcx_put_char(count, ch, f);
  122.         count = 1;
  123.         ch = image->data[x];
  124.         }
  125.     }
  126.     delete image;
  127.     fclose(f);
  128.     }
  129. ////////////////////////
  130. int pcx_file_scr(char* name, loc pos, int* cells, int mode)
  131.     {
  132.     if(cells[0] == -1)
  133.     return 1;
  134.     FILE* f = fopen(name, "rb");
  135.     pcxheader p;
  136.  
  137.     if(f == NULL)
  138.     {
  139.     fclose(f);
  140.     return 0;
  141.     }
  142.     pcxstream pcxF(f);
  143.     get_pcx_header(&pcxF, &p);
  144.  
  145.     if(1 != p.bitpx || N_PLANES != p.nplanes)   // incompatible modes
  146.     return 0;
  147.  
  148.     imageP image = (imageP)malloc(p.bplin * N_PLANES + sizeof(imageType));
  149.  
  150.     image->xmax = (p.x2 - p.x1 + 1 + 7) / 8 * 8 - 1;
  151.     image->ymax = 0;
  152.  
  153.     int x;  int y = 0;  int count;
  154.     int plane;
  155.  
  156.     plane = x = (p.nplanes - 1) * p.bplin;  // start of last plane
  157.     int shift = 2 * p.bplin;
  158.     int height = p.y2 - p.y1 + 1;
  159.     int height1;
  160.     if(cells != NULL)
  161.     {
  162.     int i = 0;
  163.     while(cells[i] != -1)
  164.         i++;
  165.     height1 = (cells[i - 1] + 80) / 80 * pScreenSet->cell_height
  166.         - pos.Y;
  167.     height = height > height1 ? height1 : height;
  168.     }
  169.     int top = cells == NULL ? 0
  170.     : cells[0] / 80 * pScreenSet->cell_height - pos.Y;
  171.     imageP work = (imageP)malloc(p.bplin * N_PLANES + sizeof(imageP));
  172.     work->ymax = 0;
  173.  
  174.     while(y <= height)
  175.     {
  176.     unsigned char ch = pcxF.get();         // read char
  177.     if((ch & 0xC0 )==0xC0)                 // if two upper bits == 1
  178.         {
  179.         count = 63 & ch;                   // use 6 low bits as counter
  180.         ch = pcxF.get();
  181.         for(int j = 0; j < count; j++)
  182.         {
  183.         image->data[x] = ch;
  184.         x++;
  185.         if(x == p.bplin)
  186.             {
  187.             if(y >= top)
  188.             putimage(pos.X, pos.Y + y, image, cells, work,
  189.                  p.bplin, mode);
  190.             x = plane;
  191.             y++;
  192.             }
  193.         else
  194.             if(!(x % p.bplin))
  195.             x -= shift;
  196.         }
  197.         }
  198.     else
  199.         {
  200.         (unsigned char)(image->data[x]) = ch;
  201.         x++;
  202.         if(x == p.bplin)
  203.         {
  204.         if(y >= top)
  205.             putimage(pos.X, pos.Y + y, image, cells, work, p.bplin,
  206.                  mode);
  207.         x = plane;
  208.         y++;
  209.         }
  210.         else
  211.         if(!(x % p.bplin))
  212.             x -= shift;
  213.         }
  214.     }
  215.     delete image;
  216.     delete work;
  217.     fclose(f);
  218.     return 1;
  219.     }
  220. //////////////////////////
  221. /*
  222. void main()
  223.     {
  224.     if(!init_KNOW_HOW())
  225.     return;
  226.  
  227. //    int LIST[] = { 40, 120, 200, 280, 360, 440, 520, -1 };
  228.  
  229. //    pcx_file_scr("about.pcz", loc(0, 0), LIST, COPY_PUT);
  230.     pcx_file_scr("g.pcx", loc(0, 0));
  231.     pcx_scr_file(rect(64, 40, 191, 300), "work.pcx", 1);
  232.     pcx_file_scr("work.pcx", loc(0, 0));
  233.     close_KNOW_HOW();
  234.     closegraph();
  235.     }
  236.  
  237. */